/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.sentry;

import io.sentry.exception.InvalidSentryTraceHeaderException;
import io.sentry.protocol.SentryId;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Locale;

/**
 * Represents HTTP header "sentry-trace".
 *
 * @since 2021-06-02
 **/
public final class SentryTraceHeader {
    /**
     * SENTRY_TRACE_HEADER
     */
    public static final String SENTRY_TRACE_HEADER = "sentry-trace";
    private final @NotNull SentryId traceId;
    private final @NotNull SpanId spanId;
    private final @Nullable Boolean sampled;

    /**
     * constructor
     *
     * @param traceId SentryId
     * @param spanId SpanId
     * @param sampled Boolean
     */
    public SentryTraceHeader(
        final @NotNull SentryId traceId,
        final @NotNull SpanId spanId,
        final @Nullable Boolean sampled) {
        this.traceId = traceId;
        this.spanId = spanId;
        this.sampled = sampled;
    }

    /**
     * constructor
     *
     * @param value String
     * @throws InvalidSentryTraceHeaderException exception
     */
    public SentryTraceHeader(final @NotNull String value) throws InvalidSentryTraceHeaderException {
        final String[] parts = value.split("-", -1);
        if (parts.length < 2) {
            throw new InvalidSentryTraceHeaderException(value);
        } else if (parts.length == 3) {
            this.sampled = "1".equals(parts[2]);
        } else {
            this.sampled = null;
        }
        this.traceId = new SentryId(parts[0]);
        this.spanId = new SpanId(parts[1]);
    }

    /**
     * getName
     *
     * @return String
     */
    public @NotNull String getName() {
        return SENTRY_TRACE_HEADER;
    }

    /**
     * get value
     *
     * @return value
     */
    public @NotNull String getValue() {
        if (sampled != null) {
            return String.format(Locale.ROOT, "%s-%s-%s", traceId, spanId, sampled ? "1" : "0");
        } else {
            return String.format(Locale.ROOT, "%s-%s", traceId, spanId);
        }
    }

    public @NotNull SentryId getTraceId() {
        return traceId;
    }

    public @NotNull SpanId getSpanId() {
        return spanId;
    }

    public @Nullable Boolean isSampled() {
        return sampled;
    }
}
